package com.fira.api.service.impl;

import com.alibaba.fastjson.JSON;
import com.fira.api.domain.dto.EduStudentDTO;
import com.fira.api.domain.dto.StuRegistrationDTO;
import com.fira.api.domain.vo.EduStudentCourseVo;
import com.fira.api.service.IStudentService;
import com.fira.common.core.domain.AjaxResult;
import com.fira.common.utils.DateUtils;
import com.fira.edu.domain.*;
import com.fira.edu.domain.vo.ParentStudentsVO;
import com.fira.edu.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author henryGui
 * @version V1.0
 * @Title: StuRegistrationServiceImpl
 * @Package com.fira.api.service.impl
 * @Description: TODO
 * @date 2021-10-11 下午10:01
 */
@Slf4j
@Service
public class StudentServiceImpl implements IStudentService {

    @Autowired
    private IEduStudentService iEduStudentService;

    @Autowired
    private IEduParentService iEduParentService;
    @Autowired
    private IEduStuParentRefService iEduStuParentRefService;

    @Autowired
    private IEduStudentTakesService iEduStudentTakesService;

    @Autowired
    private IEduStudentCourseService iEduStudentCourseService;//学生课时信息

    @Autowired
    private IEduStudentSettleService iEduStudentSettleService;//学员课程交费结算

    @Autowired
    private IEduCourseService eduCourseService;

    @Autowired
    private IEduClassService eduClassService;


    @Override
    @Transactional
    public AjaxResult saveRegistrationOrder(StuRegistrationDTO registrationDTO) {
        log.info("接收新生报名信息：{}", JSON.toJSONString(registrationDTO));
        EduStudent student = new EduStudent();
        BeanUtils.copyProperties(registrationDTO.getEduStudent(), student);

        if (student.getTenantId() == null) {
            return AjaxResult.error("保存失败，找不到对应的机构");
        }
        EduStudentCourse eduStudentCourse=registrationDTO.getEduStudentCourse() ;
        EduStudentSettle studentSettle=registrationDTO.getEduStudentSettle();
        if (StringUtils.isNotBlank(student.getId())) {
            return this.saveOldRegistrationOrder(student.getId(),eduStudentCourse,studentSettle);
        }else{
            return this.saveNewRegistrationOrder(student,registrationDTO.getParentList(),registrationDTO.getTakesList(),eduStudentCourse,studentSettle);
        }


    }

    public AjaxResult saveNewRegistrationOrder(EduStudent student,List<EduParent> parentList,List<EduStudentTakes> takesList,
                                               EduStudentCourse eduStudentCourse ,EduStudentSettle studentSettle) {

        if (parentList == null || parentList.size()<=0) {
            return AjaxResult.error("保存失败，家长信息不能为空");
        }
//        if (takesList == null || takesList.size()<=0) {
//            return AjaxResult.error("保存失败，接送时间信息不能为空");
//        }

        String stuName = student.getStudentName();

        String studentId = this.isExistStudent(parentList, stuName, student.getTenantId());
        log.info("当前学员是否存在={},{},{}", StringUtils.isNotBlank(studentId), studentId, JSON.toJSONString(student));
        int result = 0;
        if (StringUtils.isBlank(studentId)) {//当前学员不存在则新增
            student.setStatus("1");//有效
            result = iEduStudentService.insertEduStudent(student);
            studentId = student.getId();
        } else {
            result = 1;
        }
        AjaxResult ajaxResult=null;
        log.info("保存学员信息结果={},{}", result, JSON.toJSONString(student));
        if (result > 0 && StringUtils.isNotBlank(studentId)) {
            //绑定家长信息与学员信息
            this.bindParentsAndStuRef(parentList, studentId);
            //录入学员接送时间
            this.bindStudentTakesTimes(takesList, studentId);
            //录入选课信息和结算信息
            ajaxResult= this.saveCourseAndSettle(studentId,eduStudentCourse,studentSettle);
        }
        return ajaxResult==null?AjaxResult.success("保存失败"):ajaxResult;
    }


    public AjaxResult saveOldRegistrationOrder(String studentId,EduStudentCourse eduStudentCourse ,EduStudentSettle studentSettle) {
        EduStudent eduStudent=iEduStudentService.selectEduStudentById(studentId);
        if (eduStudent == null) {
            return AjaxResult.error("保存失败，查询当前学员信息不存在");
        }
        return this.saveCourseAndSettle(studentId,eduStudentCourse,studentSettle);
    }

    //录入选课信息和结算信息
    private AjaxResult saveCourseAndSettle(String studentId,EduStudentCourse eduStudentCourse ,EduStudentSettle studentSettle ) {
        String orderNo = "";
        int result = -1;
        if (StringUtils.isNotBlank(studentId) && eduStudentCourse!=null  && studentSettle!=null) {
            //录入报课信息
            eduStudentCourse.setStudentId(studentId);
            eduStudentCourse.setStatus("1");
            EduStudentCourse studentCourse = isExsitStudentCourse(eduStudentCourse);
            if(studentCourse != null){
                //将课时update到原来的学生课时数据中
                studentCourse.setGiveClassHours(studentCourse.getGiveClassHours()+eduStudentCourse.getGiveClassHours());
                studentCourse.setTotalClassHours(studentCourse.getTotalClassHours()+eduStudentCourse.getGiveClassHours());
                studentCourse.setUnuseClassHours(studentCourse.getUnuseClassHours()+eduStudentCourse.getGiveClassHours());
                result = iEduStudentCourseService.updateEduStudentCourse(studentCourse);
            }else{
                result = iEduStudentCourseService.insertEduStudentCourse(eduStudentCourse);
            }
            if (result > 0) {
                //录入结算信息
                studentSettle.setStatus("1");
                studentSettle.setStudentId(studentId);
                orderNo = buildOrderNo();
                studentSettle.setOrderNo(orderNo);
                result = iEduStudentSettleService.insertEduStudentSettle(studentSettle);
                if (result <= 0) {
                    log.error("录入学员{}结算信息异常:{}", studentId, JSON.toJSONString(studentSettle));
                    throw new RuntimeException("录入学员结算信息异常");
                }
            } else {
                log.error("录入学员{}课时信息异常:{}", studentId, JSON.toJSONString(eduStudentCourse));
                throw new RuntimeException("录入学员课时信息异常");
            }
        }else{
            return AjaxResult.error("保存失败");
        }
        return AjaxResult.success("保存成功", orderNo);
    }

    private String isExistStudent(List<EduParent> parentList, String studentName, String tenantId) {
        List<String> phoneList = parentList.stream().map(EduParent::getParentPhone).collect(Collectors.toList());

        List<ParentStudentsVO> list = iEduStudentService.selectStudentAndParentList(phoneList, studentName, tenantId);
        if (list != null && list.size() > 0) {
            return list.get(0).getStudentId();
        }
        return "";
    }

    /**
     * 查询学生班级课程信息是否存在
     * @param eduStudentCourse
     * @return
     */
    private EduStudentCourse isExsitStudentCourse(EduStudentCourse eduStudentCourse){
        EduStudentCourse studentCourse = new EduStudentCourse();
        studentCourse.setStudentId(eduStudentCourse.getStudentId());
        studentCourse.setCourseId(eduStudentCourse.getCourseId());
        studentCourse.setClassId(eduStudentCourse.getClassId());
        List<EduStudentCourse> studentCourseList = iEduStudentCourseService.selectEduStudentCourseList(studentCourse);
        if(CollectionUtils.isNotEmpty(studentCourseList)){
            return studentCourseList.get(0);
        }
        return null;
    }

    private String buildOrderNo() {
        return "D" + new Date().getTime() + RandomStringUtils.randomNumeric(6);
    }


    @Override
    public AjaxResult selectEduStudentList(EduStudentDTO eduStudentDTO) {
        EduStudent student = new EduStudent();
        BeanUtils.copyProperties(eduStudentDTO, student);
        student.setTenantId(eduStudentDTO.getTenantId());
        return AjaxResult.success("查询成功", iEduStudentService.selectEduStudentList(student));
    }

    @Override
    public AjaxResult selectStudentInfoById(String id) {
        EduStudent student = iEduStudentService.selectEduStudentById(id);
        try {
            if (student.getStudentBirthday() != null) {
                Integer age = DateUtils.getAge(student.getStudentBirthday());
                student.setAge(age);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success("查询成功", student);
    }

    /**
     * 查询学生报读课程(包括在读和历史)
     *
     * @param id
     * @return
     */
    @Override
    public AjaxResult selectStudentCourseById(String id) {
        EduStudentCourse reqCourse = new EduStudentCourse();
        reqCourse.setStudentId(id);
        //查询所有的报课信息
        List<EduStudentCourse> list = iEduStudentCourseService.selectEduStudentCourseList(reqCourse);
        EduStudentCourseVo eduStudentCourseVo = new EduStudentCourseVo();
        if (list != null && list.size() > 0) {
            list.forEach(item -> {
                EduCourse course = eduCourseService.selectEduCourseById(item.getCourseId());
                item.setCourseName(course.getCourseName());
                item.setCourseType(course.getCourseType());
                if (StringUtils.isNotBlank(item.getClassId())) {
                    item.setClassName(eduClassService.selectEduClassById(item.getClassId()).getClassName());
                }
            });
            List<EduStudentCourse> onlineList = list.stream().filter(item -> item.getUnuseClassHours() > 0).collect(Collectors.toList());
            List<EduStudentCourse> historyList = list.stream().filter(item -> item.getUnuseClassHours() <= 0).collect(Collectors.toList());
            eduStudentCourseVo.setHistoryCourseList(historyList);
            eduStudentCourseVo.setOnLineCourseList(onlineList);
        }
        return AjaxResult.success("查询成功", eduStudentCourseVo);
    }


    /**
     * 查询学生报读课程(历史)
     *
     * @param id
     * @return
     */
    @Override
    public List<EduStudentCourse> selectHistoryCourseById(String id) {
        EduStudentCourse reqCourse = new EduStudentCourse();
        reqCourse.setStudentId(id);
        //查询所有的报课信息
        List<EduStudentCourse> list = iEduStudentCourseService.selectEduStudentCourseList(reqCourse);
        if (list == null || list.size() == 0) {
            return new ArrayList<>();
        }

        /**
         * 历史课程列表
         */
        return list.stream().filter(item -> item.getUnuseClassHours() <= 0).collect(Collectors.toList());

    }

    /**
     * 查询学生报读课程(在读)
     *
     * @param id
     * @return
     */
    @Override
    public List<EduStudentCourse> selectOnlineCourseById(String id) {
        EduStudentCourse reqCourse = new EduStudentCourse();
        reqCourse.setStudentId(id);
        //查询所有的报课信息
        List<EduStudentCourse> list = iEduStudentCourseService.selectEduStudentCourseList(reqCourse);
        if (list == null || list.size() == 0) {
            return new ArrayList<>();
        }

        /**
         * 在读课程列表
         */
        return list.stream().filter(item -> item.getUnuseClassHours() > 0).collect(Collectors.toList());

    }


    /**
     * 查询学生订单信息
     *
     * @param studentId
     * @return
     */
    @Override
    public AjaxResult selectStudentOrderById(String studentId) {
        EduStudentSettle settle = new EduStudentSettle();
        settle.setStudentId(studentId);
        return AjaxResult.success("查询成功", iEduStudentSettleService.selectEduStudentSettleList(settle));
    }


    /**
     * 绑定家长信息与学员信息
     *
     * @param parentList 家长集合
     * @param studentId  学生id
     * @return
     */
    private boolean bindParentsAndStuRef(List<EduParent> parentList, String studentId) {

        List<String> parentPhones = parentList.stream().map(EduParent::getParentPhone).collect(Collectors.toList());

        //查询家长是否已经存在
        //匹配手机号查找已存在的家长信息
        List<EduParent> existParentList = iEduParentService.selectEduParentListByPhones(parentPhones);
        //已存在家长信息的phone集合
        List<String> existParentPhones = existParentList.stream().map(EduParent::getParentPhone).collect(Collectors.toList());
        List<String> existParentIds = existParentList.stream().map(EduParent::getId).collect(Collectors.toList());
        //去处已存在的家长phone后以备建立关系
        List<EduParent> notExistParentList = parentList.stream().filter(item -> !existParentPhones.contains(item.getParentPhone())).collect(Collectors.toList());
        //去处已存在的家长后，新增家长信息
        if (notExistParentList != null && notExistParentList.size() > 0) {
            List<String> newInsertListIds = this.batchSaveParents(notExistParentList);
            existParentIds.addAll(newInsertListIds); //已存在的id和新增产生的id合并以备建立学员与家长关系
        }
        log.info("=========开始绑定家长{}与学员{}关系", existParentIds, studentId);

        //查询家长学生关系表是否已经存在（排除该学生与家长已经建立关系），否则新增
        EduStuParentRef stuParentRef = new EduStuParentRef();
        stuParentRef.setStudentId(studentId);
        List<EduStuParentRef> existRefList = iEduStuParentRefService.selectEduStuParentRefList(stuParentRef);
        List<String> existRefParentIds = existRefList.stream().map(EduStuParentRef::getParentId).collect(Collectors.toList());

        int reslut = -1;
        for (int i = 0; i < existParentIds.size(); i++) {
            if (existRefParentIds.contains(existParentIds.get(i))) {
                continue;
            }
            stuParentRef = new EduStuParentRef();
            stuParentRef.setParentId(existParentIds.get(i));
            stuParentRef.setStudentId(studentId);
            reslut = iEduStuParentRefService.insertEduStuParentRef(stuParentRef);
            if (reslut <= 0) {
                log.error("绑定家长与学员信息异常:{}", JSON.toJSONString(stuParentRef));
                throw new RuntimeException("保存家长信息异常");
            }
        }

        return true;
    }

    /**
     * 批量保存家长信息
     *
     * @param list 家长id集合
     * @return
     */
    private List<String> batchSaveParents(List<EduParent> list) {
        List<String> parentIds = new ArrayList<>();
        EduParent parent = null;
        int reslut = 0;
        //如果超过一定数量，此处需要优化批量插入
        for (int i = 0; i < list.size(); i++) {
            parent = list.get(i);
            reslut = iEduParentService.insertEduParent(parent);
            if (reslut > 0) {
                parentIds.add(parent.getId());
            } else {
                log.error("保存家长信息异常:{}", JSON.toJSONString(parent));
                throw new RuntimeException("保存家长信息异常");
            }
        }
        return parentIds;
    }

    private boolean bindStudentTakesTimes(List<EduStudentTakes> list, String studentId) {
        int reslut = -1;
        EduStudentTakes takes = null;
        for (int i = 0; i < list.size(); i++) {
            takes = list.get(i);
            takes.setStudentId(studentId);
            reslut = iEduStudentTakesService.insertEduStudentTakes(takes);
            if (reslut <= 0) {
                log.error("保存学员接送信息异常:{}", JSON.toJSONString(takes));
                throw new RuntimeException("保存学员接送信息异常");
            }
        }
        return true;
    }

}
